package DesignPattern;

import DP.CopyBook;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class Singleton {
    public static void main(String[] args){
        try {
            CopyBook cb= SingletonFactory.getInstance(CopyBook.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
//phoneix的做法 单利工厂
class SingletonFactory{
    private static final Map<String, Object> instanceMap = new HashMap<>(1024);

    public static <T> T getInstance(Class<T> clazz)throws Exception{
        String name = clazz.getName();
        T instance = (T)instanceMap.get(name);
        if(instance == null){
            synchronized (clazz){
                instance = (T)instanceMap.get(name);
                if(instance == null){
                    //注意这里的写法，java 9之后是这样了
                    instance = clazz.getConstructor().newInstance();
                    if(instance == null){
                        throw new Exception("init instance fail");
                    }
                    instanceMap.put(name, instance);
                }
            }
        }
        return instance;
    }
}

//饱汉
class Singleton1{
    //volatile避免半个对象的问题
    private static volatile Singleton singleton = null;
    private Singleton1(){//我个2B，还想加个抛异常。。不能加，不然，都一直没法初始化
    }
    public static Singleton getInstance(){
        if(singleton == null){
            synchronized (Singleton1.class){//这里必须加，双检锁
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

//饿汉
class Singleton2{
    //因为类加载器的问题
    private static Singleton singleton = new Singleton();
    private Singleton2(){
    }
    public static Singleton getInstance(){
        return singleton;
    }
}

//Holder模式
class Singleton3{
    //这里这个static的很重要
    private static class SingletonHolder{
        private static final Singleton3 singleton = new Singleton3();
        private SingletonHolder(){}
    }
    private Singleton3(){
    }
    public static Singleton3 getInstance(){
        return SingletonHolder.singleton;
    }
}

//常量方式
enum Singleton4{
    INSTANCE;
    public void what(){}
}
